package sso;

import Algorithm.Base64;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;


/**
 * @version V1.0
 * @desc AESUtil 加密工具类
 */
public class AESUtil {

    private static final String KEY_ALGORITHM = "AES";
    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";// 默认的加密算法


    private static final String AES_PUB_KEY = "anxl_sso_aess_pub_key";
    private static final String pwdKey = "anxl_sso_pwd_key";
    // 30分钟重新获取授权
    public static final int COOKIE_EXPIRE_TIME = 24 * 60 * 60;


    /**
     * AESUtil 加密操作
     *
     * @param content
     *            待加密内容
     * @param password
     *            加密密码
     * @return 返回Base64转码后的加密数据
     */
    public static String encrypt(String content, String password) {
        try {
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 创建密码器

            byte[] byteContent = content.getBytes("utf-8");

            cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(password));// 初始化为加密模式的密码器

            byte[] result = cipher.doFinal(byteContent);// 加密

            String s = Base64.encode(result);// 通过Base64转码返回
            return s;
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    /**
     * AESUtil 解密操作
     *
     * @param content
     * @param password
     * @return
     */
    public static String decrypt(String content, String password) {

        try {
            // 实例化
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);

            // 使用密钥初始化，设置为解密模式
            cipher.init(Cipher.DECRYPT_MODE, getSecretKey(password));

            // 执行操作
            byte[] result = cipher.doFinal(Base64.decode(content));
            String s = new String(result, "utf-8");
            return s;
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    /**
     * 生成加密秘钥
     *
     * @return
     */
    private static SecretKeySpec getSecretKey(final String key) {
        if (null == key || key.length() == 0) {
            throw new NullPointerException("key not is null");
        }
        SecretKeySpec key2 = null;
        try {

            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(key.getBytes());

            KeyGenerator kgen = KeyGenerator.getInstance(KEY_ALGORITHM);
            kgen.init(128, random);
            SecretKey secretKey = kgen.generateKey();
            byte[] enCodeFormat = secretKey.getEncoded();
            key2 = new SecretKeySpec(enCodeFormat, KEY_ALGORITHM);
        } catch (NoSuchAlgorithmException ex) {
            ex.printStackTrace();
        }
        return key2;
    }

    public static String md5(String saveTime, String maxTime, String vaule) {
        try {
            //logger.info("try md5: saveTime:{}, maxTime:{}, value:{}", saveTime, maxTime, vaule);
            // 获取 MessageDigest 对象，参数为 MD5 字符串，表示这是一个 MD5 算法（其他还有 SHA1 算法等）：
            MessageDigest md5 = MessageDigest.getInstance("MD5");

            String info = pwdKey + ":" + saveTime + ":" + maxTime + ":" + vaule;
            // update(byte[])方法，输入原数据
            // 类似StringBuilder对象的append()方法，追加模式，属于一个累计更改的过程
            md5.update(info.getBytes("UTF-8"));
            // digest()被调用后,MessageDigest对象就被重置，即不能连续再次调用该方法计算原数据的MD5值。可以手动调用reset()方法重置输入源。
            // digest()返回值16位长度的哈希值，由byte[]承接
            byte[] md5Array = md5.digest();
            // byte[]通常我们会转化为十六进制的32位长度的字符串来使用,本文会介绍三种常用的转换方法

            String md5Str = bytesToHex1(md5Array);
            return md5Str;
        } catch (NoSuchAlgorithmException e) {
            return "";
        } catch (UnsupportedEncodingException e) {
            return "";
        }
    }

    private static String bytesToHex1(byte[] md5Array) {
        StringBuilder strBuilder = new StringBuilder();
        for (int i = 0; i < md5Array.length; i++) {
            int temp = 0xff & md5Array[i];// TODO:此处为什么添加 0xff & ？
            String hexString = Integer.toHexString(temp);
            if (hexString.length() == 1) {// 如果是十六进制的0f，默认只显示f，此时要补上0
                strBuilder.append("0").append(hexString);
            } else {
                strBuilder.append(hexString);
            }
        }
        return strBuilder.toString();
    }

    public static void main(String[] args) {
        String s = "hello,您好";
        String pwd = "anxl_sso_aess_pub_key";

        System.out.println("s:" + s);

        String s1 = AESUtil.encrypt(s, pwd);
        System.out.println("s1:" + s1);

        System.out.println("s2:" + AESUtil.decrypt(s1, pwd));


        String token = "e9557378d8b5487d92597b96d6906c6f";
        String saveTime = System.currentTimeMillis() + "";
        int maxTime = COOKIE_EXPIRE_TIME;
        String signToken = md5(saveTime, maxTime + "", token);

        String cookieValue = signToken + "&&" + saveTime + "&&" + maxTime + "&&" + token;
        // 加密
        cookieValue = AESUtil.encrypt(cookieValue, AES_PUB_KEY);
        System.out.println("加密数据："+cookieValue);
        System.out.println("-----------");

        cookieValue = "GKfaCY2NkoOCp/on3XF982J3dNvc26fY1NiT1+75exQerAN3DTd+U+o9iBikjOyVz8AazttKU/vK5NsRRWWftYpCD8NLLtsS37Y1tvD4aYGJpg1VtdsTwu9zLM5GgOpIJbsNqI7QQFyaftGGaxGJHbVJLfUqkoROGDcyLGvmOu4=\n";

        // 解密
        cookieValue = AESUtil.decrypt(cookieValue, AES_PUB_KEY);
        System.out.println(cookieValue);
        String cookieStrings[] = cookieValue.split("&&");
        if (null != cookieStrings && 4 == cookieStrings.length) {
            System.out.println("signToken="+cookieStrings[0]);
            System.out.println("saveTime="+ cookieStrings[1]);
            System.out.println("maxTime="+cookieStrings[2]);
            System.out.println("taken="+ cookieStrings[3]);
        }


    }

}
